﻿//
// Author: Ruxo Zheng (http://ruxozheng.spaces.live.com/)
//
// This file is distributed under CPOL 1.0 License (http://www.codeproject.com/info/cpol10.aspx).
//

using System;

namespace RZ.Web
{
    sealed class HtmlJScriptContentLexer : HtmlLexer
    {
        public HtmlJScriptContentLexer(HtmlLexer lexer)
            : base(lexer.Content)
        {
            this.cursor = lexer.Cursor;
        }

        public Boolean IsBeginLineComment()
        {
            return MoveCursor( ValidLength(2) && L(0) == '/' && L(1) == '/', 2);
        }

        public Boolean IsBeginBlockComment()
        {
            return MoveCursor( ValidLength(2) && L(0) == '/' && L(1) == '*', 2 );
        }

        const String EndScript = "</script";

        public Boolean IsEndScript()
        {
            return MoveCursor(CheckInsensitive(EndScript), EndScript.Length);
        }

        public Boolean GetContentLine(out String content)
        {
            Int32 startText = this.cursor;

            Int32 runnableLength = ValidContentLength;

            while (runnableLength > 0 && Read() != '\n')
                --runnableLength;

            if (startText == this.cursor)
                content = String.Empty;
            else
                content = GetContent(startText);

            return true;
        }

        public Boolean GetBlockCommentText(out String content)
        {
            Int32 startText = this.cursor;

            Int32 runnableLength = ValidContentLength;

            while (runnableLength >= 2 && !(L(0) == '*' && L(1) == '/'))
            {
                --runnableLength;
                ++this.cursor;
            }

            if (runnableLength < 2) // then, there is no */ in content.
                this.cursor += runnableLength;  // make it EOC

            content = GetContent(startText);

            return true;
        }

        public Boolean GetQuoteText(out String content)
        {
            Char quoteChar = L(0);

            if (quoteChar != '"' && quoteChar != '\'')
            {
                content = null;
                return false;
            }

            Int32 startText = ++this.cursor;

            Int32 runnableLength = ValidContentLength;

            while (runnableLength > 0 && L(0) != quoteChar)
            {
                if (runnableLength >= 2 && L(0) == '\\')
                {
                    ++this.cursor;
                    --runnableLength;
                }
                ++this.cursor;
                --runnableLength;
            }

            content = GetContent(startText);

            if (!EOC)   // have the quote matched.
                ++this.cursor;
            return true;
        }

        public Boolean GetText(out String content)
        {
            Int32 startText = this.cursor;
            Int32 saveCursor = this.cursor;

            while (!EOC)
            {
                Char c = L(0);

                if (c == '\'' || c == '"')
                    break;
                if (c == '/' && (IsBeginLineComment() || IsBeginBlockComment()))
                    break;
                if (c == '<' && IsEndScript())
                    break;

                saveCursor = ++this.cursor;
            }

            this.cursor = saveCursor;

            if (startText == this.cursor)
            {
                content = null;
                return false;
            }
            else
            {
                content = GetContent(startText);
                return true;
            }
        }
    }
}
